package com.suning.sawp.service.impl.customer;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import javax.annotation.Resource;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.joda.time.LocalDate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.google.common.eventbus.Subscribe;
import com.suning.framework.dal.client.DalClient;
import com.suning.rsf.consumer.ServiceLocator;
import com.suning.sawp.constants.ClerkConstants;
import com.suning.sawp.constants.ConfigConstants;
import com.suning.sawp.constants.ErrorCodeConstants;
import com.suning.sawp.dto.common.ReturnMsg;
import com.suning.sawp.dto.customer.ArriveStoreCalendar;
import com.suning.sawp.dto.customer.ArriveStoreCustListDto;
import com.suning.sawp.dto.customer.ClerkCustValidResult;
import com.suning.sawp.dto.customer.ClerkFollowCustRecord;
import com.suning.sawp.dto.customer.CustInfoDetailDto;
import com.suning.sawp.dto.customer.CustInfoDto;
import com.suning.sawp.dto.customer.CustInfoListEx;
import com.suning.sawp.dto.customer.CustLabel;
import com.suning.sawp.dto.customer.CustWillComm;
import com.suning.sawp.dto.customer.CustshopFrequency;
import com.suning.sawp.dto.esb.AccountAlias;
import com.suning.sawp.dto.esb.CustSocietyInfoStruct;
import com.suning.sawp.dto.esb.LocateMemberInfo;
import com.suning.sawp.dto.esb.QuerySocialityInfoResp;
import com.suning.sawp.dto.mainpush.StoreManDto;
import com.suning.sawp.intf.dao.IndexCardTaskDaoService;
import com.suning.sawp.intf.esb.MemberInfoService;
import com.suning.sawp.intf.esb.ShopFrequencyService;
import com.suning.sawp.intf.storeman.StoreManService;
import com.suning.sawp.po.bi.BIIndexTaskCardEntity;
import com.suning.sawp.po.bi.StoreRegMemberDetailDEntity;
import com.suning.sawp.po.customer.BaseTagGrade;
import com.suning.sawp.po.customer.ClerkCustInfo;
import com.suning.sawp.po.customer.ClerkCustWillProduct;
import com.suning.sawp.po.customer.CustFollowRecord;
import com.suning.sawp.po.customer.CustInfo;
import com.suning.sawp.po.customer.CustLabelRel;
import com.suning.sawp.po.customer.ShareClerkCustInfo;
import com.suning.sawp.service.impl.bi.support.BIAsyncListener;
import com.suning.sawp.service.impl.dao.ClerkCustRelDaoService;
import com.suning.sawp.service.impl.oga.OgaService;
import com.suning.sawp.service.util.AESUtils;
import com.suning.sawp.service.util.ConfigUtil;
import com.suning.sawp.service.util.DJStringUtils;
import com.suning.sawp.service.util.DateUtils;
import com.suning.sawp.service.util.SCMConfigUtil;
import com.suning.stms.dto.OuterPotCustInfoDTO;
import com.suning.stms.dto.PotCallRecordInfoDTO;
import com.suning.stms.dto.PotCustBuyTendencyDTO;
import com.suning.stms.dto.PotCustInfoDTO;
import com.suning.stms.dto.ResponseContent;
import com.suning.stms.service.PotCustManagerService;
import com.suning.vgs.follow.remote.intf.StoreConsumerService;
import com.suning.vgs.follow.remote.store.ConsumerBehaviorDto;
import com.suning.vgs.follow.remote.store.ConsumerBehaviorType;

/**
 * 
 * 〈一句话功能简述〉<br>
 * 〈功能详细描述〉
 * 
 * @author 12061748
 * @see [相关类/方法]（可选）
 * @since [产品/模块版本] （可选）
 */
@Service("clerkCustRelService")
public class ClerkCustRelService implements InitializingBean {

    private static final Logger LOGGER = LoggerFactory.getLogger(ClerkCustRelService.class);

    @Resource
    ClerkCustRelDaoService clerkCustRelDaoService;

    @Resource
    MemberInfoService memberInfoService;

    @Resource
    StoreManService storeManService;

    @Resource
    DalClient dalClient;

    @Resource
    OgaService ogaService;

    /**
     * 访问记录服务
     */
    @Autowired
    StoreConsumerService storeConsumerService;
    
    @Autowired
    IndexCardTaskDaoService indexCardTaskDaoService;

    PotCustManagerService potCustManagerService = ServiceLocator.getService(PotCustManagerService.class, "");

    @Resource
    ShopFrequencyService shopFrequencyService;

    @Autowired
    BIAsyncListener asyncListener;

    @Value("#{settingConfig[cust_level_prefix]}")
    String custLevelPrefix;

    @Value("#{settingConfig[cmf_head_prefix]}")
    String cmfHeadPrefix;

    private static final Map<String, String> CUST_LEVEL = new HashMap<String, String>();

    static {
        CUST_LEVEL.put("161000000100", "V0");
        CUST_LEVEL.put("161000000110", "V1");
        CUST_LEVEL.put("161000000120", "V2");
        CUST_LEVEL.put("161000000130", "V3");
        CUST_LEVEL.put("161000000140", "V4");
        CUST_LEVEL.put("161000000150", "超级粉丝");
        CUST_LEVEL.put("161000000160", "V0");
        CUST_LEVEL.put("161000000000", "暂无等级");
        CUST_LEVEL.put("161099999998", "暂无等级");
        CUST_LEVEL.put("161099999999", "暂无等级");
    }

    private static final int QUERY_SIZE = 100;

    /**
     * 
     * 功能描述: 校验店员是否已经拓展了此客户<br>
     * 〈功能详细描述〉
     * 
     * @param staffId
     * @param mobile
     * @return
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    public ReturnMsg<ClerkCustValidResult> validCustExist(String staffId, String mobile, String custSource) {
        ReturnMsg<ClerkCustValidResult> returnMsg = new ReturnMsg<ClerkCustValidResult>();
        if (StringUtils.isBlank(mobile) || StringUtils.isBlank(custSource)) {
            returnMsg.setError(ErrorCodeConstants.ERR_0001);
            return returnMsg;
        }
        try {
            ClerkCustValidResult clerkCustValidResult = new ClerkCustValidResult();
            CustInfoDto dto = new CustInfoDto();
            // 根据手机号查询对应的客户ID
            CustInfo custInfo = clerkCustRelDaoService.queryCustInfoByMobile(mobile);
            if (null != custInfo) {
                StoreManDto manDto = storeManService.queryStoreManAttachInfo(staffId);
                if (ClerkCustInfo.CustSource.OUT_DEV.equals(custSource)) {
                    // 外拓关系新增，先判断此手机号对应客户是否在门店已经被记录过了
                    boolean hasExist = clerkCustRelDaoService.validCustHasRecordInStore(custInfo.getCustId(),
                            manDto.getStoreCode());
                    if (hasExist) {
                        // 关系已经存在
                        returnMsg.setError(ErrorCodeConstants.ERR_1017);
                        return returnMsg;
                    }
                }
                // 根据工号和客户ID查询店员客户关系
                ClerkCustInfo clerkCustInfo = clerkCustRelDaoService.queryClerkCustInfo(staffId, custInfo.getCustId(),
                        manDto.getStoreCode());
                if (null != clerkCustInfo) {
                    // 店员客户关系存在，已经被此店员记录
                    // 关系已存在则返回客户关系ID
                    dto.setCustRelId(clerkCustInfo.getCustRelId());
                    clerkCustValidResult.setValidResult(ClerkCustValidResult.ValidResult.YES);
                } else {
                    // 店员客户关系不存在，尚未被此店员记录
                    clerkCustValidResult.setValidResult(ClerkCustValidResult.ValidResult.NO);
                }
            } else {
                // 如果查询不到对应的客户信息，则尚未被此店员记录
                clerkCustValidResult.setValidResult(ClerkCustValidResult.ValidResult.NO);
            }

            if (ClerkCustValidResult.ValidResult.NO.equals(clerkCustValidResult.getValidResult())) {
                // 根据手机号查询会员接口取，此用户的会员编码、生日、客户等级
                // 根据手机号查询会员编码
                LocateMemberInfo memberInfo = memberInfoService.locateMemberByMobileNo(mobile);
                if (null != memberInfo && StringUtils.isNotBlank(memberInfo.getCustNum())) {
                    // 手机号为会员，根据会员编码查询会员详情
                    String custNo = memberInfo.getCustNum();
                    List<String> custNumList = new ArrayList<String>();
                    custNumList.add(custNo);
                    QuerySocialityInfoResp infoResp = memberInfoService.querySocialityInfoAConstellation(custNumList);
                    // 加密会员编码
                    dto.setCustNo(AESUtils.encrypt(custNo, ConfigConstants.AES_KEY));
                    if (null != infoResp && null != infoResp.getBody()) {
                        if (CollectionUtils.isNotEmpty(infoResp.getBody().getCustSocietyInfoStructList())) {
                            CustSocietyInfoStruct infoStruct = infoResp.getBody().getCustSocietyInfoStructList().get(0);
                            // 客户等级
                            dto.setCustLevel(getCustLevelPicUrl(CUST_LEVEL.get(infoStruct.getCustLevelNum())));
                            // 客户生日
                            dto.setBirthday(infoStruct.getBirthdate());
                        }
                    }
                }
                // 加密手机号
                dto.setMobile(AESUtils.encrypt(mobile, ConfigConstants.AES_KEY));
            }
            clerkCustValidResult.setCustInfo(dto);
            returnMsg.setData(clerkCustValidResult);
        } catch (Exception e) {
            returnMsg.setError(ErrorCodeConstants.ERR_0002);
            Object[] args = { staffId, mobile };
            LOGGER.error("ClerkCustRelService.validCustExist error. staffId:{}, mobile:{}", args, e);
        }

        return returnMsg;
    }

    /**
     * 
     * 功能描述: 拼接会员等级图片地址<br>
     * 〈功能详细描述〉
     * 
     * @param custLevel
     * @return
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    private String getCustLevelPicUrl(String custLevel) {
        return custLevelPrefix + custLevel + ".png";
    }

    /**
     * 
     * 功能描述: 查询所有的客户评级列表<br>
     * 〈功能详细描述〉
     * 
     * @return
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    public ReturnMsg<List<BaseTagGrade>> getAllCustRates() {
        List<BaseTagGrade> grades = clerkCustRelDaoService.queryTagsByType(BaseTagGrade.TypeConstants.TYPE_GRADE);
        ReturnMsg<List<BaseTagGrade>> returnMsg = new ReturnMsg<List<BaseTagGrade>>();
        returnMsg.setData(grades);
        return returnMsg;
    }

    /**
     * 
     * 功能描述: 查询所有客户标签列表<br>
     * 〈功能详细描述〉
     * 
     * @return
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    public ReturnMsg<List<CustLabel>> getAllCustLabels() {
        ReturnMsg<List<CustLabel>> returnMsg = new ReturnMsg<List<CustLabel>>();
        List<BaseTagGrade> grades = clerkCustRelDaoService.queryTagsByType(BaseTagGrade.TypeConstants.TYPE_TAG);
        List<CustLabel> labels = new ArrayList<CustLabel>();
        if (CollectionUtils.isNotEmpty(grades)) {
            for (BaseTagGrade grade : grades) {
                labels.add(new CustLabel(grade.getId(), grade.getName()));
            }
        }
        returnMsg.setData(labels);
        return returnMsg;
    }

    /**
     * 
     * 功能描述: 编辑客户信息<br>
     * 〈功能详细描述〉
     * 
     * @return
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    public ReturnMsg<String> editCustInfo(CustInfoDetailDto detailDto, String staffId) {
        ReturnMsg<String> returnMsg = new ReturnMsg<String>();
        // 校验参数合法性
        if (null == detailDto || !detailDto.checkParams()) {
            // 参数校验不通过
            LOGGER.error("ClerkCustRelService.editCustInfo param is empty.");
            returnMsg.setError(ErrorCodeConstants.ERR_0001);
            return returnMsg;
        }
        StoreManDto manDto = storeManService.queryStoreManAttachInfo(staffId);
        if (null != detailDto.getCustRelId()) {
            // 客户关系ID不为空，为更新操作
            updateClerkCustInfo(detailDto, returnMsg, manDto.getStoreCode(), staffId);
        } else {
            // 客户关系ID为空，新增
            addNewCustInfo(detailDto, returnMsg, manDto.getStoreCode(), staffId);
        }
        return returnMsg;
    }

    /**
     * 
     * 功能描述: 添加新的客户信息<br>
     * 〈功能详细描述〉
     * 
     * @param detailDto
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    @Transactional
    public void addNewCustInfo(CustInfoDetailDto detailDto, ReturnMsg<String> returnMsg, String storeCode,
            String staffId) {
        try {
            // 获取客户手机号(解密)
            String mobile = AESUtils.decrypt(detailDto.getMobile(), ConfigConstants.AES_KEY);
            // 根据手机号查询客户信息表是否已存在对应记录
            CustInfo custInfo = clerkCustRelDaoService.queryCustInfoByMobile(mobile);
            Long custId;
            if (null == custInfo) {
                // 新增客户信息记录
                custInfo = new CustInfo();
                // 改成查询会员接口取数据，不取客户端传过来的值
                LocateMemberInfo memberInfo = memberInfoService.locateMemberByMobileNo(mobile);
                if (null != memberInfo) {
                    custInfo.setCustNo(memberInfo.getCustNum());
                }
                custInfo.setMobile(mobile);
                custId = clerkCustRelDaoService.addNewCustInfo(custInfo);
                if (null == custId) {
                    LOGGER.error("ClerkCustRelService.addNewCustInfo add new custinfo fail");
                    returnMsg.setError(ErrorCodeConstants.ERR_1020);
                }
            } else {
                custId = custInfo.getCustId();
            }
            // 取客户关系来源
            String custSource = detailDto.getCustSource();
            Long actId = null;
            if (ClerkCustInfo.CustSource.OUT_DEV.equals(custSource)) {
                // 外拓关系新增，先判断此手机号对应客户是否在门店已经被记录过了
                boolean hasExist = clerkCustRelDaoService.validCustHasRecordInStore(custId, storeCode);
                if (hasExist) {
                    // 关系已经存在
                    returnMsg.setError(ErrorCodeConstants.ERR_1017);
                    return;
                } else {
                    // 关系不存在
                    actId = clerkCustRelDaoService.queryActIdByTaskId(detailDto.getTaskId(), storeCode);
                    if (null == actId) {
                        // 根据地点任务编号未能查找到活动ID
                        returnMsg.setError(ErrorCodeConstants.ERR_1018);
                        return;
                    }

                }
            }
            // 记录店员客户关系
            ClerkCustInfo clerkCustInfo = new ClerkCustInfo();
            clerkCustInfo.setAcqMobile(detailDto.getAcqMobile());
            clerkCustInfo.setAcqName(detailDto.getAcqName());
            clerkCustInfo.setActId(actId);
            clerkCustInfo.setTaskId(detailDto.getTaskId());
            clerkCustInfo.setCreateTime(new Date());
            clerkCustInfo.setUpdateTime(new Date());
            clerkCustInfo.setCustId(custId);
            clerkCustInfo.setCustRating(detailDto.getRateId());
            clerkCustInfo.setCustSource(custSource);
            clerkCustInfo.setIsKeyCust(detailDto.getIsKeyCust());
            clerkCustInfo.setRemark(detailDto.getRemark());
            clerkCustInfo.setRemarkName(detailDto.getRemarkName());
            clerkCustInfo.setStaffId(staffId);
            clerkCustInfo.setStoreCode(storeCode);
            if(StringUtils.isNotBlank(detailDto.getOrderBuyNum())){
                clerkCustInfo.setOrderBuyNum(detailDto.getOrderBuyNum());
            }
            if(StringUtils.isNotBlank(detailDto.getOrderBuyTime())){
                clerkCustInfo.setOrderBuyTime( DateUtils.getDateByStr(detailDto.getOrderBuyTime(), DateUtils.DEFAULT_DATE_PATTERN));
            }
            // 新增店员客户关系记录
            Long custRelId = clerkCustRelDaoService.addNewClerkCustInfo(clerkCustInfo);
            //更新首页导航该店员信息 ,查询该店员七天内的预约情况，并刷新首页任务标签
            updateIndexOrderMsg(staffId,storeCode);
            if (null == custRelId) {
                LOGGER.error("ClerkCustRelService.addNewCustInfo fail");
                returnMsg.setError(ErrorCodeConstants.ERR_1020);
                return;
            }
            // 如果是外拓渠道，新增成功增加外拓任务对应发展人数
            if (ClerkCustInfo.CustSource.OUT_DEV.equals(custSource)) {
                ogaService.incrCompltNum(detailDto.getTaskId(), storeCode, staffId);
            }

            // 新增客户标签, 需要判断是否存在标签
            if (CollectionUtils.isNotEmpty(detailDto.getLabels())) {
                if (detailDto.getLabels().size() > 6) {
                    // 标签列表最多6个
                    returnMsg.setError(ErrorCodeConstants.ERR_1021);
                    return;
                }
                List<CustLabelRel> rels = new ArrayList<CustLabelRel>();
                for (CustLabel label : detailDto.getLabels()) {
                    rels.add(new CustLabelRel(custRelId, label.getLabelId(), label.getLabelName(), staffId));
                }
                clerkCustRelDaoService.addNewCustLabelRels(rels);
            }
            // 新增客户意向商品，需要判断商品是否存在
            if (CollectionUtils.isNotEmpty(detailDto.getWillComms())) {
                if (detailDto.getWillComms().size() > 10) {
                    // 意向商品列表最多10个
                    returnMsg.setError(ErrorCodeConstants.ERR_1022);
                    return;
                }
                List<ClerkCustWillProduct> products = new ArrayList<ClerkCustWillProduct>();
                for (CustWillComm comm : detailDto.getWillComms()) {
                    ClerkCustWillProduct willProduct = new ClerkCustWillProduct();
                    willProduct.setCustRelId(custRelId);
                    willProduct.setBranchName(comm.getBranchName());
                    if (StringUtils.isNotBlank(comm.getCateCode())) {
                        willProduct.setCateCode(comm.getCateCode());
                        String categoryName = ConfigUtil.getConfig(ConfigConstants.SAWP_CONFIG_MAIN_PUSH_CATEGORY,
                                comm.getCateCode());
                        willProduct.setCateName(categoryName);
                    }
                    willProduct.setCommCode(comm.getCommCode());
                    willProduct.setCommName(comm.getCommName());
                    willProduct.setRemark(comm.getRemark());
                    willProduct.setStaffId(staffId);
                    products.add(willProduct);
                }
                clerkCustRelDaoService.addNewCustWillProducts(products);

                // 传千里传音的数据
                transVoipData(clerkCustInfo, custInfo, products);
            }
        } catch (Exception e) {
            LOGGER.error("ClerkCustRelService.addNewCustInfo error. params:{}", e, detailDto.toString());
            returnMsg.setError(ErrorCodeConstants.ERR_1020);
        }
    }

    /**
     * 
     * 功能描述: 新建关系时给千里传音传数据<br>
     * 〈功能详细描述〉
     * 
     * @param clerkCustInfo
     * @param custInfo
     * @param products
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    private void transVoipData(ClerkCustInfo clerkCustInfo, CustInfo custInfo, List<ClerkCustWillProduct> products) {
        try {
            // 到店和熟人的才需要传给千里传音
            if (ClerkCustInfo.CustSource.OUT_DEV.equals(clerkCustInfo.getCustSource())) {
                LOGGER.warn("新增店员客户关系为外拓，不传给千里传音, custRelId:{}", clerkCustInfo.getCustRelId());
                return;
            }
            List<OuterPotCustInfoDTO> outerPotCustInfos = new ArrayList<OuterPotCustInfoDTO>();
            OuterPotCustInfoDTO custInfoDTO = new OuterPotCustInfoDTO();
            // 计划购买意向商品
            if (CollectionUtils.isNotEmpty(products)) {
                StringBuilder builder = new StringBuilder();
                // 计划购买意向商品
                List<PotCustBuyTendencyDTO> buyTendencyDTOs = new ArrayList<PotCustBuyTendencyDTO>();
                for (ClerkCustWillProduct willProduct : products) {
                    if (StringUtils.isNotBlank(willProduct.getCateCode())) {
                        PotCustBuyTendencyDTO buyTendencyDTO = new PotCustBuyTendencyDTO();
                        // 品类编码
                        buyTendencyDTO.setTendencyCategory(willProduct.getCateCode());
                        // 品牌名称
                        buyTendencyDTO.setTendencyBand(willProduct.getBranchName());
                        // 未购买原因
                        buyTendencyDTO.setNotBuyReason("8");
                        // 意向购买分组
                        buyTendencyDTO.setTendencyGroup("1");
                        buyTendencyDTOs.add(buyTendencyDTO);
                        builder.append(willProduct.getCateCode()).append(",");
                    }
                }
                // 如果有购买品类意向的才传给千里传音数据
                if (CollectionUtils.isNotEmpty(buyTendencyDTOs)) {
                    custInfoDTO.setPotCustBuyTendencyList(buyTendencyDTOs);
                    PotCustInfoDTO potCustInfo = new PotCustInfoDTO();
                    // 会员编码
                    if (StringUtils.isBlank(custInfo.getCustNo())) {
                        potCustInfo.setCustNum("");
                    } else {
                        potCustInfo.setCustNum(custInfo.getCustNo());
                    }
                    // 手机号
                    potCustInfo.setMobile(custInfo.getMobile());
                    // 姓名
                    potCustInfo.setName(clerkCustInfo.getRemarkName());
                    // 性别
                    potCustInfo.setGender("2");
                    // 意向类型
                    potCustInfo.setBuyType("1");
                    // 意向品类
                    builder = builder.deleteCharAt(builder.length() - 1);
                    potCustInfo.setBuyCategory(builder.toString());
                    custInfoDTO.setPotCustInfo(potCustInfo);

                    // 呼叫用户信息
                    PotCallRecordInfoDTO callRecordInfoDTO = new PotCallRecordInfoDTO();
                    // 再次沟通时间, 当前时间往后延两天
                    Date commTime = DateUtils.getNextDay(new Date(), 2);
                    callRecordInfoDTO.setCommTime(commTime);
                    // 再次沟通方式
                    callRecordInfoDTO.setCommType("0");
                    // 外呼员工工号
                    callRecordInfoDTO.setEmpNo(clerkCustInfo.getStaffId());
                    // 备注不为空的传给千里传音
                    if (StringUtils.isNotBlank(clerkCustInfo.getRemark())) {
                        callRecordInfoDTO.setRemark(clerkCustInfo.getRemark());
                    } else {
                        // 否则传空字符
                        callRecordInfoDTO.setRemark("");
                    }
                    custInfoDTO.setPotCallRecordInfoDTO(callRecordInfoDTO);

                    outerPotCustInfos.add(custInfoDTO);

                    LOGGER.info("invoke potCustManagerService.importOuterPotCustInfo. params:{}", outerPotCustInfos);
                    ResponseContent<Boolean> resp = potCustManagerService.importOuterPotCustInfo(outerPotCustInfos);
                    LOGGER.info("invoke potCustManagerService.importOuterPotCustInfo. resp:{}", resp);
                }
            }
        } catch (Exception e) {
            LOGGER.error("invoke potCustManagerService failed.", e);
        }
    }

    /**
     * 
     * 功能描述: 更新店员客户关系<br>
     * 〈功能详细描述〉
     * 
     * @param detailDto
     * @param returnMsg
     * @param storeCode
     * @param staffId
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    @Transactional
    public void updateClerkCustInfo(CustInfoDetailDto detailDto, ReturnMsg<String> returnMsg, String storeCode,
            String staffId) {
        try {
            // 可以更新的客户关系内容：备注姓名、备注、客户评级、更新时间、标签列表、意向商品列表
            // 更新客户关系中非标签列表和意向商品列表
            // 校验关系ID是否存在
            CustInfoDetailDto dto = clerkCustRelDaoService.queryClerkCustInfoByRelId(detailDto.getCustRelId(),
                    storeCode);
            if (null == dto) {
                returnMsg.setError(ErrorCodeConstants.ERR_0001);
                return;
            }
            clerkCustRelDaoService.updateClerkCustInfo(detailDto, storeCode);
            
            //更新首页导航该店员信息 ,查询该店员七天内的预约情况，并刷新首页任务标签
            updateIndexOrderMsg(staffId,storeCode);
            
            // 更改客户资料时，不需要判断标签是否存在，为空代表删除
            // 更新标签列表,先删除所有相关列表信息，在新增标签列表
            clerkCustRelDaoService.delCustLabels(detailDto.getCustRelId(), staffId);
            if (CollectionUtils.isNotEmpty(detailDto.getLabels())) {
                if (detailDto.getLabels().size() > 6) {
                    // 标签列表最多6个
                    returnMsg.setError(ErrorCodeConstants.ERR_1021);
                    return;
                }
                List<CustLabelRel> rels = new ArrayList<CustLabelRel>();
                for (CustLabel label : detailDto.getLabels()) {
                    rels.add(new CustLabelRel(detailDto.getCustRelId(), label.getLabelId(), label.getLabelName(),
                            staffId));
                }
                clerkCustRelDaoService.addNewCustLabelRels(rels);
            }
            // 更新客户意向商品列表,先删除所有相关列表信息，在新增意向商品列表
            clerkCustRelDaoService.delCustWillComms(detailDto.getCustRelId(), staffId);
            if (CollectionUtils.isNotEmpty(detailDto.getWillComms())) {
                if (detailDto.getWillComms().size() > 10) {
                    // 意向商品列表最多10个
                    returnMsg.setError(ErrorCodeConstants.ERR_1022);
                    return;
                }
                List<ClerkCustWillProduct> products = new ArrayList<ClerkCustWillProduct>();
                for (CustWillComm comm : detailDto.getWillComms()) {
                    ClerkCustWillProduct willProduct = new ClerkCustWillProduct();
                    willProduct.setCustRelId(detailDto.getCustRelId());
                    willProduct.setBranchName(comm.getBranchName());
                    if (StringUtils.isNotBlank(comm.getCateCode())) {
                        // 判断品类编码是否存在
                        willProduct.setCateCode(comm.getCateCode());
                        String categoryName = ConfigUtil.getConfig(ConfigConstants.SAWP_CONFIG_MAIN_PUSH_CATEGORY,
                                comm.getCateCode());
                        willProduct.setCateName(categoryName);
                    }
                    willProduct.setCommCode(comm.getCommCode());
                    willProduct.setCommName(comm.getCommName());
                    willProduct.setRemark(comm.getRemark());
                    willProduct.setStaffId(staffId);
                    products.add(willProduct);
                }
                clerkCustRelDaoService.addNewCustWillProducts(products);
            }
        } catch (Exception e) {
            LOGGER.error("ClerkCustRelService.updateClerkCustInfo error. params:{}", e, detailDto.toString());
            returnMsg.setError(ErrorCodeConstants.ERR_1020);
        }
    }


    private void updateIndexOrderMsg(String staffId, String storeCode) {
        int count = clerkCustRelDaoService.queryIndexOrderNum(staffId, storeCode);
        LOGGER.info("updateIndexOrderMsg,staffId:{},storeCode:{},count:{}",staffId,storeCode,count);
        LocalDate nowDay = new LocalDate();
        BIIndexTaskCardEntity bIIndexTaskCardEntity = new BIIndexTaskCardEntity();
        bIIndexTaskCardEntity.setBizKey(BIIndexTaskCardEntity.BizKey.ORDER_BY);
        bIIndexTaskCardEntity.setCardType(BIIndexTaskCardEntity.CardType.CARD_002);
        bIIndexTaskCardEntity.setStaffId(staffId);
        bIIndexTaskCardEntity.setStartTime(nowDay.toDate());
//        MessageFormat mf = new MessageFormat(BIIndexTaskCardEntity.Content.ORDER_CUST_CONTENT);
        bIIndexTaskCardEntity.setTaskTips(BIIndexTaskCardEntity.Content.ORDER_CUST_CONTENT);
        bIIndexTaskCardEntity.setTitle(BIIndexTaskCardEntity.Title.ORDER_CUST);
        //如果该客户存在7天内预约客户则更新时间为有效时间
        if(count > 0){
            bIIndexTaskCardEntity.setStartTime(nowDay.toDate());
            bIIndexTaskCardEntity.setEndTime(nowDay.plusDays(7).toDate());
        }else{
            //如果该客户七天内不存在预约客户则更新时间为失效时间
            bIIndexTaskCardEntity.setStartTime(nowDay.plusYears(-1).toDate());
            bIIndexTaskCardEntity.setEndTime(nowDay.plusDays(7).toDate());
        }
        indexCardTaskDaoService.upsertIndexTaskCard(bIIndexTaskCardEntity);
    }

    
    public static void main(String[] args) {
        LocalDate nowDay = new LocalDate();
        System.out.println(nowDay.plusDays(7).toDate());
    }
    /**
     * 
     * 功能描述:查询与我关联的客户数量 <br>
     * 〈功能详细描述〉
     * 
     * @param staffCode
     * @return
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    public Long queryMyGrowCustNum(String staffCode, String storeCode) {
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("staffCode", staffCode);
        map.put("storeCode", storeCode);
        Map<String, Object> result = dalClient.queryForMap("customer.queryMyGrowCustNum", map);
        return (Long) result.get("num");
    }

    /**
     * 
     * 功能描述: 查询今日跟进人数<br>
     * 〈功能详细描述〉
     * 
     * @param staffCode
     * @return
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    public Long queryTodayFollowCustNum(String staffCode) {
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("staffCode", staffCode);
        Map<String, Object> result = dalClient.queryForMap("customer.queryTodayFollowCustNum", map);
        return (Long) result.get("num");
    }

    /**
     * 
     * 功能描述: 查询非会员的总记录数<br>
     * 〈功能详细描述〉
     * 
     * @param staffId
     * @param storeCode
     * @return
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    public Integer queryNoMemberNumByStaffId(String staffId, String storeCode) {
        Integer num = clerkCustRelDaoService.queryNoMemberNumByStaffId(staffId, storeCode);
        return null == num ? Integer.valueOf("0") : num;
    }

    /**
     * 
     * 功能描述: 查询活动或者任务下的客户数量<br>
     * 〈功能详细描述〉
     * 
     * @param staffCode
     * @return
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    public Long queryCustNum(String taskId, String actId) {
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("taskId", taskId);
        map.put("actId", actId);
        Map<String, Object> result = dalClient.queryForMap("customer.queryCustNumByStoreTaskId", map);
        return (Long) result.get("num");
    }

    /**
     * 
     * 功能描述:删除活动 <br>
     * 〈功能详细描述〉
     * 
     * @param actId
     * @return
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    @Transactional
    public void deleteActByActId(String actId) {
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("actId", actId);
        // 删除活动
        dalClient.execute("customer.deleteActByActId", map);
        // 删除门店任务
        dalClient.execute("customer.deleteStoreTask", map);
        // 删除店员任务
        dalClient.execute("customer.deleteClerkTask", map);
        // 删除活动和店员关系表
        dalClient.execute("customer.deleteRelByActId", map);
    }

    /**
     * 
     * 功能描述: 删除任务<br>
     * 〈功能详细描述〉
     * 
     * @param taskId
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    @Transactional
    public void deleteStoreTaskByTaskId(String taskId, String storeCode) {
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("taskId", taskId);
        map.put("storeCode", storeCode);
        // 删除门店任务
        dalClient.execute("customer.deleteStoreTask", map);
        // 删除店员任务
        dalClient.execute("customer.deleteClerkTask", map);
        // 删除活动与店员的关系表（sql实现）
        dalClient.execute("customer.deleteActClerkRel", map);
    }

    /**
     * 
     * 功能描述:查询自己当前任务下的拓展会员 <br>
     * 〈功能详细描述〉
     * 
     * @param staffCode
     * @param taskId
     * @return
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    public List<CustInfoDetailDto> queryOutGrowCustList(String staffCode, String taskId) {
        StoreManDto manDto = storeManService.queryStoreManAttachInfo(staffCode);
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("taskId", taskId);
        map.put("staffCode", staffCode);
        map.put("storeCode", manDto.getStoreCode());
        map.put("custSource", ClerkCustInfo.CustSource.OUT_DEV);
        List<CustInfoListEx> custListEx = dalClient.queryForList("customer.queryOutGrowCustListEx", map,
                CustInfoListEx.class);
        List<CustInfoDetailDto> detailDtos = convertCustList(custListEx, null);
        return detailDtos;
    }

    /**
     * 
     * 功能描述: <br>
     * 〈功能详细描述〉
     * 
     * @param custRelId
     * @return
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    public ReturnMsg<CustInfoDetailDto> queryCustInfoDetail(Long custRelId, String staffId) {
        ReturnMsg<CustInfoDetailDto> returnMsg = new ReturnMsg<CustInfoDetailDto>();
        StoreManDto manDto = storeManService.queryStoreManAttachInfo(staffId);
        // 查询客户关系ID对应的详情
        CustInfoDetailDto detailDto = clerkCustRelDaoService.queryClerkCustInfoByRelId(custRelId,
                manDto.getStoreCode());
        if (null != detailDto) {
            // 刚刚查询会员接口补充会员编码字段，适用于以前是非会员，后注册为会员，更新客户的会员编码信息
            boolean justUpdateCustNo = false;
            if (StringUtils.isBlank(detailDto.getCustNo())) {
                // 原先为非会员，则查询手机号对应的是否为会员
                // 根据手机号查询会员编码
                LocateMemberInfo memberInfo = memberInfoService.locateMemberByMobileNo(detailDto.getMobile());
                if (null != memberInfo && StringUtils.isNotBlank(memberInfo.getCustNum())) {
                    // 手机号为会员，根据会员编码查询会员详情
                    String custNo = memberInfo.getCustNum();
                    clerkCustRelDaoService.updateCustInfoCustNo(detailDto.getCustId(), custNo);
                    detailDto.setCustNo(custNo);
                    // 设置更新了会员编码标识
                    justUpdateCustNo = true;
                }
            }
            // 查询会员接口,取生日、客户等级、头像地址 易购头像地址规则
            if (StringUtils.isNotBlank(detailDto.getCustNo())) {
                List<String> custNumList = new ArrayList<String>();
                custNumList.add(detailDto.getCustNo());
                QuerySocialityInfoResp infoResp = memberInfoService.querySocialityInfoAConstellation(custNumList);
                if (null != infoResp && null != infoResp.getBody()) {
                    if (CollectionUtils.isNotEmpty(infoResp.getBody().getCustSocietyInfoStructList())) {
                        CustSocietyInfoStruct infoStruct = infoResp.getBody().getCustSocietyInfoStructList().get(0);
                        // 客户等级
                        detailDto.setCustLevel(getCustLevelPicUrl(CUST_LEVEL.get(infoStruct.getCustLevelNum())));
                        // 客户生日
                        detailDto.setBirthday(infoStruct.getBirthdate());
                        // 头像
                        detailDto.setHeadPicUrl(getCmfHeadPicUrl(infoStruct));
                        // 判断手机号是否与会员的一致，不一致则更新会员最新的
                        if (!justUpdateCustNo) {
                            // 非刚刚更新会员编码的记录，走比较手机号操作
                            checkAndUpdateMobile(infoStruct, detailDto.getMobile(), detailDto.getCustId());
                        }
                    }
                }
                // 会员画像地址
                detailDto.setMemberPortraitUrl(DJStringUtils.getMemberProtraitUrl(detailDto.getCustNo()));
                // 会员首复购标识
                // 取首复购标识
                List<String> custNos = new ArrayList<String>();
                custNos.add(detailDto.getCustNo());
                Map<String, String> frequencyList = shopFrequencyService.queryShopFrequency(custNos);
                CustshopFrequency frequency = DJStringUtils.getDealType(frequencyList.get(detailDto.getCustNo()));
                detailDto.setShopStatus(frequency.getDealType());
                // 会员编码加密
                detailDto.setCustNo(AESUtils.encrypt(detailDto.getCustNo(), ConfigConstants.AES_KEY));
            }
            // 查询客户关系ID对应的标签列表
            List<CustLabel> labels = clerkCustRelDaoService.queryCustLabels(custRelId, detailDto.getStaffId());
            // 查询客户关系ID对应的客户意向商品列表
            List<CustWillComm> comms = clerkCustRelDaoService.queryCustWillComms(custRelId, detailDto.getStaffId());
            detailDto.setLabels(labels);
            detailDto.setWillComms(comms);
            // 手机号加密
            detailDto.setMobile(AESUtils.encrypt(detailDto.getMobile(), ConfigConstants.AES_KEY));
            returnMsg.setData(detailDto);
        } else {
            // 查询店员客户关系失败
            LOGGER.error("ClerkCustRelService.queryCustInfoDetail not find, custRelId:{}", custRelId);
            returnMsg.setError(ErrorCodeConstants.ERR_0002);
        }

        return returnMsg;
    }

    /**
     * 
     * 功能描述: 判断<br>
     * 〈功能详细描述〉
     * 
     * @param infoStruct
     * @param dbMobile
     * @param custId
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    private void checkAndUpdateMobile(CustSocietyInfoStruct infoStruct, String dbMobile, Long custId) {
        if (CollectionUtils.isNotEmpty(infoStruct.getAccountAliasList())) {
            String cmfMobile = null;
            for (AccountAlias alias : infoStruct.getAccountAliasList()) {
                if (AccountAlias.AliasType.MOBILE.equals(alias.getAliasType())) {
                    cmfMobile = alias.getAliasName();
                    break;
                }
            }
            if (null != cmfMobile && !cmfMobile.equals(dbMobile)) {
                // 查询cmfMobile是否已经存在对应的记录
                CustInfo custInfo = clerkCustRelDaoService.queryCustInfoByMobile(cmfMobile);
                if (null != custInfo) {
                    LOGGER.warn("ClerkCustRelService.checkAndUpdateMobile 促发了删除action, cmfMobile:{}, custId:{}",
                            cmfMobile, custId);
                    // 如果以前存在对应的记录，按产品要求删除之，删除与之相关的所有关联记录
                    // CLERK_CUST_INFO 店员-客户信息表
                    // 根据custId查询所有相关联的客户关系记录
                    List<ClerkCustInfo> clerkCustInfos = clerkCustRelDaoService.queryClerkCustInfosByCustId(custId);
                    if (CollectionUtils.isNotEmpty(clerkCustInfos)) {
                        for (ClerkCustInfo info : clerkCustInfos) {
                            // CUST_LABEL_REL 客户和标签关联表
                            clerkCustRelDaoService.delCustLabels(info.getCustRelId(), info.getStaffId());
                            // CLERK_CUST_WILL_PRODUCT 店员-客户-意向商品表
                            clerkCustRelDaoService.delCustWillComms(info.getCustRelId(), info.getStaffId());
                            // CUST_FOLLOW_RECORD 客户跟进记录表
                            clerkCustRelDaoService.delCustFollowRecords(info.getCustRelId(), info.getStaffId());
                        }
                    }
                    // CUST_INFO 客户信息表
                    clerkCustRelDaoService.delCustInfo(custId);
                }
                // 会员返回手机号与原有记录DB的手机号发生变化
                clerkCustRelDaoService.updateCustInfoMobile(custId, cmfMobile);
            }
        }
    }

    /**
     * 
     * 功能描述: <br>
     * 〈功能详细描述〉
     * 
     * @param custNo
     * @param sysHeadPicFlag
     * @param sysHeadPicNum
     * @return
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    private String getCmfHeadPicUrl(CustSocietyInfoStruct infoStruct) {
        if (CustSocietyInfoStruct.SysHeadPicFlag.ECIF_NO.equals(infoStruct.getSysHeadPicFlag())) {
            // 非自定义头像
            return cmfHeadPrefix + infoStruct.getCustNum() + "_00_120x120.jpg?v=" + infoStruct.getSysHeadPicNum();
        } else {
            // 系统头像
            return cmfHeadPrefix + "0000000000_01_120x120.jpg";
        }
    }

    /**
     * 
     * 功能描述: 查询我的客户列表<br>
     * 〈功能详细描述〉
     * 
     * @param staffId
     * @return
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    public ReturnMsg<List<CustInfoDetailDto>> getMyCustInfoList(String staffId, String promoteDate) {
        ReturnMsg<List<CustInfoDetailDto>> returnMsg = new ReturnMsg<List<CustInfoDetailDto>>();
        // 根据工号获取店员信息
        StoreManDto manDto = storeManService.queryStoreManAttachInfo(staffId);
        // 查询店员的客户信息列表（以标签维度）
        List<CustInfoListEx> listExs = clerkCustRelDaoService.getMyCustInfoList(staffId, manDto.getStoreCode(),
                promoteDate);
        // 查询待跟进的客户关系列表
        List<Long> waitFollowCusts = clerkCustRelDaoService.getWaitFollowRecords(staffId);
        // 组装返回数据
        List<CustInfoDetailDto> detailDtos = convertCustList(listExs, waitFollowCusts);
        returnMsg.setData(detailDtos);
        return returnMsg;
    }

    /**
     * 
     * 功能描述: 组装客户列表所需数据<br>
     * 〈功能详细描述〉
     * 
     * @param listExs
     * @param waitFollowCusts
     * @return
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    private List<CustInfoDetailDto> convertCustList(List<CustInfoListEx> listExs, List<Long> waitFollowCusts) {
        List<CustInfoDetailDto> detailDtos = new ArrayList<CustInfoDetailDto>();
        if (CollectionUtils.isNotEmpty(listExs)) {
            Map<Long, List<CustLabel>> labelMap = new HashMap<Long, List<CustLabel>>();
            Map<Long, CustInfoDetailDto> custRelMap = new HashMap<Long, CustInfoDetailDto>();
            List<String> custList = new ArrayList<String>();
            Map<String, String> shopMap = new HashMap<String, String>();
            for (CustInfoListEx ex : listExs) {
                // 处理标签
                List<CustLabel> labels = labelMap.get(ex.getCustRelId());
                if (CollectionUtils.isEmpty(labels)) {
                    labels = new ArrayList<CustLabel>();
                }
                if (null != ex.getLabelId()) {
                    CustLabel label = new CustLabel();
                    label.setLabelId(ex.getLabelId());
                    label.setLabelName(ex.getLabelName());
                    labels.add(label);
                }

                labelMap.put(ex.getCustRelId(), labels);

                // 判断客户关系详情是否已存在
                if (!custRelMap.containsKey(ex.getCustRelId())) {
                    CustInfoDetailDto dto = new CustInfoDetailDto();
                    dto.setCustRelId(ex.getCustRelId());
                    dto.setIsKeyCust(ex.getIsKeyCust());
                    dto.setRateId(ex.getRateId());
                    dto.setRateName(ex.getRateName());
                    // 兼容外拓老接口
                    dto.setCustRating(ex.getRateId());
                    dto.setCustRatingName(ex.getRateName());
                    // 兼容外拓老接口
                    dto.setCustId(ex.getCustId());
                    dto.setActId(ex.getActId());
                    dto.setCustSource(ex.getCustSource());
                    dto.setStaffId(ex.getStaffId());
                    dto.setRemark(ex.getRemark());
                    dto.setRemarkName(ex.getRemarkName());
                    dto.setStoreCode(ex.getStoreCode());
                    dto.setOrderBuyTime(ex.getOrderBuyTime());
                    dto.setArriveTime(ex.getUpdateTime());
                    if (StringUtils.isNotBlank(ex.getMobile())) {
                        dto.setEncryptMobile(AESUtils.encrypt(ex.getMobile(), ConfigConstants.AES_KEY));
                    }
                    if (StringUtils.isNotBlank(ex.getCustNo())) {
                        custList.add(ex.getCustNo());
                        dto.setCustNo(ex.getCustNo());
                    }
                    custRelMap.put(ex.getCustRelId(), dto);
                }
            }

            // 查询会员接口查询用户的首复购状态
            // 会员接口有限制，每批次查询100
            int size = custList.size();
            int i = 0;
            while (i < size) {
                if (size - i < QUERY_SIZE) {
                    // 最后一批次
                    List<String> list = custList.subList(i, size);
                    Map<String, String> map = shopFrequencyService.queryShopFrequency(list);
                    shopMap.putAll(map);
                } else {
                    List<String> list = custList.subList(i, i + QUERY_SIZE);
                    Map<String, String> map = shopFrequencyService.queryShopFrequency(list);
                    shopMap.putAll(map);
                }
                i += QUERY_SIZE;
            }

            Set<Entry<Long, CustInfoDetailDto>> entries = custRelMap.entrySet();
            for (Entry<Long, CustInfoDetailDto> entry : entries) {
                CustInfoDetailDto detailDto = entry.getValue();
                Long custRelId = entry.getKey();
                List<CustLabel> labels = labelMap.get(custRelId);
                detailDto.setLabels(labels);
                // 兼容外拓下人员老接口
                detailDto.setCustLabels(labels);
                // 判断是否需要跟进
                if (null != waitFollowCusts && waitFollowCusts.contains(custRelId)) {
                    detailDto.setWaitFollow(CustInfoDetailDto.WaitFollow.YES);
                } else {
                    detailDto.setWaitFollow(CustInfoDetailDto.WaitFollow.NO);
                }
                // 处理是否为会员、会员首复购状态
                if (StringUtils.isNotBlank(detailDto.getCustNo())) {
                    // 会员
                    detailDto.setIsMember(CustInfoDetailDto.IsMember.YES);
                    CustshopFrequency frequency = DJStringUtils.getDealType(shopMap.get(detailDto.getCustNo()));
                    detailDto.setShopStatus(frequency.getDealType());
                } else {
                    // 非会员
                    detailDto.setIsMember(CustInfoDetailDto.IsMember.NO);
                    // 非会员购物状态置为未购物
                    detailDto.setShopStatus(CustshopFrequency.DealType.NO_BUY);
                }
                // 将处理完的客户关系详情结果添加至返回列表中
                detailDtos.add(detailDto);
            }
        }
        return detailDtos;
    }

    /**
     * 
     * 功能描述: 查询到店客户列表<br>
     * 〈功能详细描述〉
     * 
     * @param staffId
     * @param queryDate
     * @return
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    public ReturnMsg<ArriveStoreCustListDto> getArriveStoreCustList(String staffId, String queryDate) {
        ReturnMsg<ArriveStoreCustListDto> returnMsg = new ReturnMsg<ArriveStoreCustListDto>();
        // 根据工号获取店员信息
        StoreManDto manDto = storeManService.queryStoreManAttachInfo(staffId);
        Date beginTime;
        List<ArriveStoreCalendar> calendar = null;
        if (StringUtils.isNotBlank(queryDate)) {
            beginTime = DateUtils.getDateByStr(queryDate, DateUtils.YYYYMMDD_PATTERN);
        } else {
            // 查询时间为空则代表查询今日
            beginTime = DateUtils.getNowZeroPoint();
            // 近7天日历数据， 当天查询返回日历
            calendar = getArriveStoreCalendar();
        }
        Date endTime = DateUtils.getNextDay(beginTime, 1);
        // 查询店员的客户信息列表（以标签维度）
        List<CustInfoListEx> listExs = clerkCustRelDaoService.getArriveStoreCustList(staffId, manDto.getStoreCode(),
                beginTime, endTime);
        // 组装返回客户数据
        List<CustInfoDetailDto> detailDtos = convertCustList(listExs, null);

        returnMsg.setData(new ArriveStoreCustListDto(detailDtos, calendar));
        return returnMsg;
    }

    
    public ReturnMsg<List<CustInfoDetailDto>> getArriveStoreCustListNew(String staffId, int index, int page) {

        ReturnMsg<List<CustInfoDetailDto>> returnMsg = new ReturnMsg<List<CustInfoDetailDto>>();
        // 根据工号获取店员信息
        StoreManDto manDto = storeManService.queryStoreManAttachInfo(staffId);
        // 查询店员的客户信息列表（以标签维度）
        List<CustInfoListEx> listExs = clerkCustRelDaoService.getArriveStoreCustPageList(staffId, manDto.getStoreCode(), index, page);
        // 组装返回客户数据
        List<CustInfoDetailDto> detailDtos = convertCustList(listExs, null);
        Collections.sort(detailDtos, new Comparator<CustInfoDetailDto>(){  
            
            /*  
             * int compare(SchemePlace o1, SchemePlace o2) 返回一个基本类型的整型，  
             * 返回负数表示：o1 小于o2，  
             * 返回0 表示：o1和o2相等，  
             * 返回正数表示：o1大于o2。  
             */  
            public int compare(CustInfoDetailDto o1, CustInfoDetailDto o2) { 
                if(StringUtils.isNotBlank(o2.getArriveTime())  && StringUtils.isNotBlank(o1.getArriveTime()) ){
                    //进行升序排列  
                    if(  o1.getArriveTime().compareTo(o2.getArriveTime()) < 0){  
                        return 1;  
                    }  
                    if(  o1.getArriveTime().compareTo(o2.getArriveTime()) > 0){  
                        return -1;  
                    }  
                    return 0;  
                }else{
                    return 0;
                }
            }  
        });   
        returnMsg.setData(detailDtos);
        return returnMsg;
    
    }
    
    /**
     * 
     * 功能描述: 取近7天的日历列表<br>
     * 〈功能详细描述〉
     * 
     * @return
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    private List<ArriveStoreCalendar> getArriveStoreCalendar() {
        List<ArriveStoreCalendar> calendars = new ArrayList<ArriveStoreCalendar>();
        Date now = new Date();
        for (int i = 6; i >= 0; i--) {
            Date time = DateUtils.getNextDay(now, -1 * i);
            String date = DateUtils.getDateStrByFormat(time, DateUtils.YYYYMMDD_PATTERN);
            String week = DateUtils.getWeekOfDate(time);
            calendars.add(new ArriveStoreCalendar(date, week));
        }
        return calendars;
    }

    /**
     * 
     * 功能描述: 查询熟人推荐列表<br>
     * 〈功能详细描述〉
     * 
     * @param staffId
     * @return
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    public ReturnMsg<List<CustInfoDetailDto>> getAcqRecommendCusts(String staffId) {
        ReturnMsg<List<CustInfoDetailDto>> returnMsg = new ReturnMsg<List<CustInfoDetailDto>>();
        // 根据工号获取店员信息
        StoreManDto manDto = storeManService.queryStoreManAttachInfo(staffId);
        // 查询店员的客户信息列表（以标签维度）
        List<CustInfoListEx> listExs = clerkCustRelDaoService.getAcqRecommendCusts(staffId, manDto.getStoreCode());
        // 组装返回数据
        List<CustInfoDetailDto> detailDtos = convertCustList(listExs, null);
        returnMsg.setData(detailDtos);
        return returnMsg;
    }

    /**
     * 
     * 功能描述: <br>
     * 〈功能详细描述〉
     * 
     * @param staffId
     * @param followRemark
     * @param followResult
     * @param followType
     * @param nextFollowTime
     * @param custRelId
     * @return
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    public ReturnMsg<String> clerkFollowCust(String staffId, String followRemark, String followResult,
            Integer followType, String nextFollowTime, Long custRelId) {
        ReturnMsg<String> returnMsg = new ReturnMsg<String>();
        // 校验参数合法性
        if (null == followType || null == custRelId) {
            returnMsg.setError(ErrorCodeConstants.ERR_0002);
        } else {
            if (!(CustFollowRecord.FollowType.THOUSAND_SOUND == followType
                    || CustFollowRecord.FollowType.WECHAT == followType)) {
                returnMsg.setError(ErrorCodeConstants.ERR_0002);
            } else {
                // 根据工号获取店员信息
                StoreManDto manDto = storeManService.queryStoreManAttachInfo(staffId);
                // 判断custRelId是否与工号匹配
                ClerkCustInfo clerkCustInfo = clerkCustRelDaoService.queryClerkCustInfoByStaffIdAndRelId(staffId,
                        custRelId, manDto.getStoreCode());
                if (null == clerkCustInfo) {
                    returnMsg.setError(ErrorCodeConstants.ERR_0002);
                } else {
                    // 参数OK，可以进入下一步
                    CustFollowRecord followRecord = new CustFollowRecord();
                    followRecord.setCreateTime(new Date());
                    followRecord.setCustRelId(custRelId);
                    followRecord.setFollowType(followType);
                    followRecord.setNextFollowTime(nextFollowTime);
                    followRecord.setRemark(followRemark);
                    followRecord.setResult(followResult);
                    followRecord.setStaffId(staffId);
                    clerkCustRelDaoService.addNewCustFollowRecord(followRecord);

                    // 调用服务,保存客户行为
                    saveConsumerBehavior(staffId, clerkCustInfo.getCustId(), followType);
                }
            }
        }

        return returnMsg;
    }

    /**
     * 
     * 功能描述: 保存用户行为<br>
     * 〈功能详细描述〉
     *
     * @param staffId
     * @param custRelId
     * @param followType
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    private void saveConsumerBehavior(String staffId, Long custId, Integer followType) {
        LOGGER.info("saveConsumerBehavior enter, staffId={},custId={},followType={}",
                new Object[] { staffId, custId, followType });
        try {
            // 增加服务端记录店+客户端的客户行为轨迹
            CustInfo custInfo = clerkCustRelDaoService.queryCustInfoByCustId(custId);
            if (null == custInfo) {
                // 不存在客户关系, 直接返回
                LOGGER.error("saveConsumerBehavior error, custRelId={}, custInfo is null", custId);
                return;
            }
            ConsumerBehaviorDto conDto = new ConsumerBehaviorDto();
            // 没有客户编码时, 记默认客户编码0000000000
            conDto.setCustNo(StringUtils.isBlank(custInfo.getCustNo()) ? "0000000000" : custInfo.getCustNo());
            conDto.setStaffId(staffId);
            conDto.setPhoneNo(custInfo.getMobile());
            conDto.setBehaviorTime(System.currentTimeMillis());
            if (CustFollowRecord.FollowType.THOUSAND_SOUND == followType) {
                conDto.setBehaviorType(ConsumerBehaviorType.PHONE_FOLLOW);
                conDto.setBehaviorName("电话跟进");
            } else if (CustFollowRecord.FollowType.WECHAT == followType) {
                conDto.setBehaviorType(ConsumerBehaviorType.WECHAT_FOLLOW);
                conDto.setBehaviorName("微信跟进");
            }
            storeConsumerService.upsertConsumerBehavior(conDto);
        } catch (Exception e) {
            LOGGER.error("saveConsumerBehavior error", e);
        }
        LOGGER.info("saveConsumerBehavior exit, staffId={},custRelId={},followType={}",
                new Object[] { staffId, custId, followType });
    }

    /**
     * 
     * 功能描述: <br>
     * 〈功能详细描述〉
     * 
     * @param custRelId
     * @param staffId
     * @return
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    public ReturnMsg<List<ClerkFollowCustRecord>> queryCustFollowRecords(Long custRelId, String staffId) {
        ReturnMsg<List<ClerkFollowCustRecord>> returnMsg = new ReturnMsg<List<ClerkFollowCustRecord>>();
        List<ClerkFollowCustRecord> records = new ArrayList<ClerkFollowCustRecord>();
        // 根据客户关系ID和门店编码查询客户关系，取对应关系的工号，共享客户列表进入的共用此接口，需要绕一下
        StoreManDto manDto = storeManService.queryStoreManAttachInfo(staffId);
        if (null != manDto) {
            // 查询所属工号
            String belongStaffId = clerkCustRelDaoService.queryClerkCustInfoBelongStaffId(custRelId,
                    manDto.getStoreCode());
            if (StringUtils.isNotBlank(belongStaffId)) {
                List<CustFollowRecord> list = clerkCustRelDaoService.queryCustFollowRecords(belongStaffId, custRelId);
                if (CollectionUtils.isNotEmpty(list)) {
                    for (CustFollowRecord followRecord : list) {
                        ClerkFollowCustRecord record = new ClerkFollowCustRecord();
                        record.setFollowRemark(followRecord.getRemark());
                        record.setFollowTime(DateUtils.getDateStrByFormat(followRecord.getCreateTime(),
                                DateUtils.ACCURATE_MINUTES_PATTERN));
                        record.setFollowType(followRecord.getFollowType());
                        record.setResult(followRecord.getResult());

                        records.add(record);
                    }
                }
            } else {
                returnMsg.setError(ErrorCodeConstants.ERR_0001);
                LOGGER.error("clerkCustRelService.queryCustFollowRecords custRelId:{}, staffId:{}", custRelId, staffId);
            }
        }

        returnMsg.setData(records);
        return returnMsg;
    }

    public ReturnMsg<String> setKeyCust(Long custRelId, Integer opType, String staffId) {
        ReturnMsg<String> returnMsg = new ReturnMsg<String>();
        // 校验参数合法性
        if (null == opType || null == custRelId) {
            returnMsg.setError(ErrorCodeConstants.ERR_0002);
        } else {
            if (!(ClerkCustInfo.KeyCustOpType.SET_KEY == opType || ClerkCustInfo.KeyCustOpType.CANCEL_KEY == opType)) {
                returnMsg.setError(ErrorCodeConstants.ERR_0002);
            } else {
                // 根据工号获取店员信息
                StoreManDto manDto = storeManService.queryStoreManAttachInfo(staffId);
                // 判断custRelId是否与工号匹配
                ClerkCustInfo clerkCustInfo = clerkCustRelDaoService.queryClerkCustInfoByStaffIdAndRelId(staffId,
                        custRelId, manDto.getStoreCode());
                if (null == clerkCustInfo) {
                    returnMsg.setError(ErrorCodeConstants.ERR_0002);
                } else {
                    clerkCustRelDaoService.setKeyCust(custRelId, manDto.getStoreCode(), opType);
                }
            }
        }

        return returnMsg;
    }

    /**
     * 
     * 功能描述: 非会员外拓、熟人、到店渠道，发展注册会员，增加店员客户绑定关系<br>
     * 〈功能详细描述〉
     * 
     * @param detailDto
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    public void addClerkCustRelWhenNoOutGrow(CustInfoDetailDto detailDto) {
        // 异常处理掉，不影响正常注册等流程
        try {
            // 根据手机号查询客户信息表是否已存在对应记录
            CustInfo custInfo = clerkCustRelDaoService.queryCustInfoByMobile(detailDto.getMobile());
            Long custId;
            if (null == custInfo) {
                // 新增客户信息记录
                custInfo = new CustInfo();
                custInfo.setCustNo(detailDto.getCustNo());
                custInfo.setMobile(detailDto.getMobile());
                custId = clerkCustRelDaoService.addNewCustInfo(custInfo);
                if (null == custId) {
                    LOGGER.error(
                            "ClerkCustRelService.addClerkCustRelWhenNoOutGrow add new custinfo fail, staffId:{},custNo:{}",
                            detailDto.getStaffId(), detailDto.getCustNo());
                }
            } else {
                custId = custInfo.getCustId();
            }

            // 记录店员客户关系
            ClerkCustInfo clerkCustInfo = new ClerkCustInfo();
            clerkCustInfo.setCreateTime(detailDto.getCreateTime());
            clerkCustInfo.setUpdateTime(detailDto.getCreateTime());
            clerkCustInfo.setCustId(custId);
            clerkCustInfo.setCustRating(detailDto.getRateId());
            clerkCustInfo.setCustSource(detailDto.getCustSource());
            clerkCustInfo.setIsKeyCust(detailDto.getIsKeyCust());
            clerkCustInfo.setRemarkName(detailDto.getRemarkName());
            clerkCustInfo.setStaffId(detailDto.getStaffId());
            clerkCustInfo.setStoreCode(detailDto.getStoreCode());
            // 新增店员客户关系记录
            Long custRelId = clerkCustRelDaoService.addNewClerkCustInfo(clerkCustInfo);
            if (null == custRelId) {
                LOGGER.error("ClerkCustRelService.addClerkCustRelWhenNoOutGrow fail staffId:{},custNo:{}",
                        detailDto.getStaffId(), detailDto.getCustNo());
                return;
            }
        } catch (Exception e) {
            LOGGER.error("ClerkCustRelService.addClerkCustRelWhenNoOutGrow exception. staffId:" + detailDto.getStaffId()
                    + ",custNo:" + detailDto.getCustNo(), e);
        }
    }

    /**
     * 
     * 功能描述: 查询共享客户关系列表<br>
     * 〈功能详细描述〉
     * 
     * @param staffId
     * @return
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    public ReturnMsg<List<CustInfoDetailDto>> queryShareCustList(String staffId) {
        ReturnMsg<List<CustInfoDetailDto>> returnMsg = new ReturnMsg<List<CustInfoDetailDto>>();
        // 根据工号获取店员信息
        StoreManDto manDto = storeManService.queryStoreManAttachInfo(staffId);
        // 查询店员的客户信息列表（以标签维度）
        List<CustInfoListEx> listExs = clerkCustRelDaoService.queryShareCustList(manDto.getStoreCode());
        // 查询待跟进的客户关系列表
        List<Long> waitFollowCusts = clerkCustRelDaoService.getWaitFollowRecords(staffId);
        // 组装返回数据
        List<CustInfoDetailDto> detailDtos = convertShareCustList(listExs, waitFollowCusts);
        returnMsg.setData(detailDtos);
        return returnMsg;
    }

    /**
     * 
     * 功能描述: 组装客户列表所需数据<br>
     * 〈功能详细描述〉
     * 
     * @param listExs
     * @param waitFollowCusts
     * @return
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    private List<CustInfoDetailDto> convertShareCustList(List<CustInfoListEx> listExs, List<Long> waitFollowCusts) {
        List<CustInfoDetailDto> detailDtos = new ArrayList<CustInfoDetailDto>();
        if (CollectionUtils.isNotEmpty(listExs)) {
            Map<Long, List<CustLabel>> labelMap = new HashMap<Long, List<CustLabel>>();
            Map<Long, CustInfoDetailDto> custRelMap = new HashMap<Long, CustInfoDetailDto>();
            for (CustInfoListEx ex : listExs) {
                // 处理标签
                List<CustLabel> labels = labelMap.get(ex.getCustRelId());
                if (CollectionUtils.isEmpty(labels)) {
                    labels = new ArrayList<CustLabel>();
                }
                if (null != ex.getLabelId()) {
                    CustLabel label = new CustLabel();
                    label.setLabelId(ex.getLabelId());
                    label.setLabelName(ex.getLabelName());
                    labels.add(label);
                }

                labelMap.put(ex.getCustRelId(), labels);

                // 判断客户关系详情是否已存在
                if (!custRelMap.containsKey(ex.getCustRelId())) {
                    CustInfoDetailDto dto = new CustInfoDetailDto();
                    dto.setCustRelId(ex.getCustRelId());
                    dto.setIsKeyCust(ex.getIsKeyCust());
                    dto.setRateId(ex.getRateId());
                    dto.setRateName(ex.getRateName());
                    dto.setRemark(ex.getRemark());
                    dto.setRemarkName(ex.getRemarkName());
                    dto.setStaffId(ex.getStaffId());
                    dto.setStaffName(ex.getStaffName());
                    custRelMap.put(ex.getCustRelId(), dto);
                }
            }

            Set<Entry<Long, CustInfoDetailDto>> entries = custRelMap.entrySet();
            for (Entry<Long, CustInfoDetailDto> entry : entries) {
                CustInfoDetailDto detailDto = entry.getValue();
                Long custRelId = entry.getKey();
                List<CustLabel> labels = labelMap.get(custRelId);
                detailDto.setLabels(labels);
                // 判断是否需要跟进
                if (null != waitFollowCusts && waitFollowCusts.contains(custRelId)) {
                    detailDto.setWaitFollow(CustInfoDetailDto.WaitFollow.YES);
                } else {
                    detailDto.setWaitFollow(CustInfoDetailDto.WaitFollow.NO);
                }
                // 将处理完的客户关系详情结果添加至返回列表中
                detailDtos.add(detailDto);
            }
        }

        return detailDtos;
    }

    /**
     * 
     * 功能描述: 重新分配店员客户关系<br>
     * 〈功能详细描述〉
     * 
     * @param custRelId
     * @param assignStaffId
     * @param staffId
     * @return
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    public ReturnMsg<String> assignShareCust(Long custRelId, String assignStaffId, String opStaffId) {
        ReturnMsg<String> returnMsg = new ReturnMsg<String>();
        Object[] args = { custRelId, assignStaffId, opStaffId };
        LOGGER.info("ClerkCustRelService.assignShareCust in. params:{}", args);
        try {
            // 检查操作人工号是否为督导或者店长
            StoreManDto manDto = storeManService.queryStoreManAttachInfo(opStaffId);
            if (!(ClerkConstants.STORE_KEEPER.equals(manDto.getPositionId())
                    || ClerkConstants.SALE_GUIDE.equals(manDto.getPositionId()))) {
                returnMsg.setError(ErrorCodeConstants.ERR_0001);
                return returnMsg;
            }
            // 1、查询共享客户关系SHARE_CLERK_CUST_INFO中的对应记录
            LOGGER.info("ClerkCustRelService.assignShareCust queryShareClerkCustInfo . custRelId:{}", custRelId);
            ShareClerkCustInfo shareClerkCustInfo = clerkCustRelDaoService.queryShareClerkCustInfo(custRelId);
            if (null != shareClerkCustInfo) {
                // 2、查询CLERK_CUST_INFO中待分配工号是否已经与此客户建立了客户关系
                boolean existsFlag = clerkCustRelDaoService.checkClerkCustInfoExists(assignStaffId,
                        shareClerkCustInfo.getCustId(), shareClerkCustInfo.getStoreCode());
                if (existsFlag) {
                    // 待分配的店员已有此客户关系，提示用户关系已存在
                    returnMsg.setError(ErrorCodeConstants.ERR_1024);
                } else {
                    clerkCustRelDaoService.dealAssginShareClerkCustInfo(assignStaffId, custRelId, shareClerkCustInfo);
                }
            } else {
                LOGGER.warn("ClerkCustRelService.assignShareCust do not query shareClerkCustInfo. custRelId:{}",
                        custRelId);
                returnMsg.setError(ErrorCodeConstants.ERR_1025);
            }
        } catch (Exception e) {
            LOGGER.error("ClerkCustRelService.assignShareCust error. params:{}", args, e);
            returnMsg.setError(ErrorCodeConstants.ERR_0002);
        }

        return returnMsg;
    }

    /**
     * 
     * 功能描述: 处理离职人员对应<br>
     * 〈功能详细描述〉
     * 
     * @param staffId
     * @param staffName
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    public void dealQuitClerkCustInfos(String staffId, String storeCode, String staffName) {
        int startIndex = 0;
        int limit = 100;
        List<ClerkCustInfo> list = clerkCustRelDaoService.queryBelongClerkCustInfos(staffId, storeCode, startIndex,
                limit);
        while (CollectionUtils.isNotEmpty(list)) {
            // 每一批次处理100条记录
            List<Map<String, Object>> shareList = new ArrayList<Map<String, Object>>();
            // 将CLERK_CUST_INFO 表中相关联的记录加入shareList，为批量插入共享客户关系表做准备，SHARE_CLERK_CUST_INFO
            for (ClerkCustInfo info : list) {
                try {
                    Map<String, Object> paramMap = new HashMap<String, Object>();
                    paramMap.put("custRelId", info.getCustRelId());
                    paramMap.put("staffId", info.getStaffId());
                    paramMap.put("custId", info.getCustId());
                    paramMap.put("remarkName", info.getRemarkName());
                    paramMap.put("remark", info.getRemark());
                    paramMap.put("custSource", info.getCustSource());
                    paramMap.put("custRating", info.getCustRating());
                    paramMap.put("createTime", info.getCreateTime());
                    paramMap.put("updateTime", info.getUpdateTime());
                    paramMap.put("isKeyCust", info.getIsKeyCust());
                    paramMap.put("taskId", info.getTaskId());
                    paramMap.put("actId", info.getActId());
                    paramMap.put("acqName", info.getAcqName());
                    paramMap.put("acqMobile", info.getAcqMobile());
                    paramMap.put("storeCode", info.getStoreCode());
                    // 加入店员姓名
                    paramMap.put("staffName", staffName);
                    shareList.add(paramMap);
                } catch (Exception e) {
                    LOGGER.error("dealQuitClerkCustInfos BeanUtils.populate fail, custRelId:{}", info.getCustRelId(),
                            e);
                    continue;
                }
            }
            if (CollectionUtils.isNotEmpty(shareList)) {
                // 批量插入
                clerkCustRelDaoService.batchAddShareClerkCustInfo(shareList);
            }

            startIndex += limit;
            list = clerkCustRelDaoService.queryBelongClerkCustInfos(staffId, storeCode, startIndex, limit);
        }
    }

    /**
     * 
     * 功能描述: <br>
     * 〈功能详细描述〉
     * 
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    @Subscribe
    public void addClerkCustInfoWhenLoadPosMember(StoreRegMemberDetailDEntity entity) {
        Long rateId = Long.valueOf(SCMConfigUtil.getConfig(ConfigConstants.DEFAULT_RATE_ID));
        List<String> custNoList = new ArrayList<String>();
        custNoList.add(entity.getMemberId());
        Map<String, String> custMobiles = memberInfoService.getMemberMobiles(custNoList);
        String account = custMobiles.get(entity.getMemberId());
        if (StringUtils.isNotBlank(account)) {
            CustInfoDetailDto detailDto = new CustInfoDetailDto();
            // 客户评级给C
            detailDto.setRateId(rateId);
            // 会员编码
            detailDto.setCustNo(entity.getMemberId());
            // 客户来源
            detailDto.setCustSource(ClerkCustInfo.CustSource.POS);
            // 非重点客户
            detailDto.setIsKeyCust(ClerkCustInfo.KeyCustOpType.CANCEL_KEY);
            // 手机号
            detailDto.setMobile(account);
            // 工号
            detailDto.setStaffId(entity.getEmployeeCd());
            // 门店编码
            detailDto.setStoreCode(entity.getStrCd());
            // 记录创建时间
            detailDto.setCreateTime(new Date());
            // 备注名，注册为手机号，以脱敏手机号作为用户名
            detailDto.setRemarkName(DJStringUtils.desensitiseMobile(account));
            addClerkCustRelWhenNoOutGrow(detailDto);
        }
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        asyncListener.register(this);
    }

    public ReturnMsg<List<CustInfoDetailDto>> queryOrderCustInfo(String staffId) {
        ReturnMsg<List<CustInfoDetailDto>> returnMsg = new ReturnMsg<List<CustInfoDetailDto>>();
        // 根据工号获取店员信息
        StoreManDto manDto = storeManService.queryStoreManAttachInfo(staffId);
        // 查询店员的客户信息列表（以标签维度）
        List<CustInfoListEx> listExs = clerkCustRelDaoService.getMyOrderInfoList(staffId, manDto.getStoreCode());
        // 组装返回数据
        List<CustInfoDetailDto> detailDtos = convertCustList(listExs, null);
        Collections.sort(detailDtos, new Comparator<CustInfoDetailDto>(){  
            
            /*  
             * int compare(SchemePlace o1, SchemePlace o2) 返回一个基本类型的整型，  
             * 返回负数表示：o1 小于o2，  
             * 返回0 表示：o1和o2相等，  
             * 返回正数表示：o1大于o2。  
             */  
            public int compare(CustInfoDetailDto o1, CustInfoDetailDto o2) {  
                if(StringUtils.isNotBlank(o2.getOrderBuyTime())  && StringUtils.isNotBlank(o1.getOrderBuyTime()) ){
                    //进行升序排列  
                    if(  o1.getOrderBuyTime().compareTo(o2.getOrderBuyTime()) < 0){  
                        return -1;  
                    }  
                    if(  o1.getOrderBuyTime().compareTo(o2.getOrderBuyTime()) > 0){  
                        return 1;  
                    }  
                    return 0;  
                }else{
                    return 0;
                }
            }  
        });   
        returnMsg.setData(detailDtos);
        return returnMsg;
    
    }
}
